package logic

import (
	"context"
	"strconv"
	"strings"

	"mall/common/resultx"
	"mall/service/backend/common/i18n"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type SetUserMetaLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSetUserMetaLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SetUserMetaLogic {
	return &SetUserMetaLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *SetUserMetaLogic) SetUserMeta(in *user.SetUserMetaReq) (*user.BaseResp, error) {
	if in.UserId == nil || *in.UserId == 0 { // 涉及多个用户 UserMetaInfo.Id 保存单个用户ID
		return l.batchIncreaseMeta(in)
	}

	res, err := l.svcCtx.CurrentUser.FindOne(l.ctx, *in.UserId)
	if err != nil {
		return nil, err
	}

	var modified bool
	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	if in.Incr != nil && in.MetaKey != nil && *in.Incr != 0 && len(strings.TrimSpace(*in.MetaKey)) > 0 {
		var step int
		if *in.Incr > 0 {
			step = int(*in.Incr)
		} else {
			step = int(*in.Incr) * -1
		}

		err = l.svcCtx.CurrentUser.IncreaseMeta(l.ctx, tx, res.ID, strings.TrimSpace(*in.MetaKey), step)
		if err != nil {
			// logrus.Info(fmt.Sprintf("SetUserMeta IncreaseMeta err: %+v", err))
			logx.Errorw("SetUserMeta IncreaseMeta err", logx.Field("detail", err.Error()))
			if err != model.ErrNotFound {
				tx.Rollback()
				return nil, err
			}
		}

		modified = true
	}

	if len(in.UserMeta) > 0 {
		for _, v := range in.UserMeta {
			if v.Key != nil && v.Value != nil && len(strings.TrimSpace(*v.Key)) > 0 && len(strings.TrimSpace(*v.Value)) > 0 {
				err = l.svcCtx.CurrentUser.UpdateMetum(l.ctx, tx, &model.UserMetum{
					UserID:    res.ID,
					MetaKey:   strings.TrimSpace(*v.Key),
					MetaValue: null.StringFrom(strings.TrimSpace(*v.Value)),
				})
				if err != nil {
					tx.Rollback()
					// logrus.Info(fmt.Sprintf("SetUserMeta UpdateMeta err: %+v", err))
					logx.Errorw("SetUserMeta UpdateMeta err", logx.Field("detail", err.Error()))
					return nil, err
				}

				modified = true
			}
		}
	}

	if modified {
		tx.Commit()
	}

	return &user.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}

func (l *SetUserMetaLogic) batchIncreaseMeta(in *user.SetUserMetaReq) (*user.BaseResp, error) {
	var modified bool
	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	if len(in.UserMeta) > 0 && in.Incr != nil && in.MetaKey != nil && *in.Incr != 0 && len(strings.TrimSpace(*in.MetaKey)) > 0 {
		var direction int
		if *in.Incr > 0 {
			direction = 1
		} else {
			direction = -1
		}
		metaKey := strings.TrimSpace(*in.MetaKey)

		for _, v := range in.UserMeta {
			if v.Id != nil && v.Value != nil && *v.Id > 0 && len(strings.TrimSpace(*v.Value)) > 0 {
				if step, err := strconv.ParseInt(strings.TrimSpace(*v.Value), 10, 32); err == nil {
					err = l.svcCtx.CurrentUser.IncreaseMeta(l.ctx, tx, *v.Id, metaKey, direction*int(step))
					if err != nil {
						// logrus.Info(fmt.Sprintf("SetUserMeta batchIncreaseMeta IncreaseMeta err: %+v", err))
						logx.Errorw("SetUserMeta batchIncreaseMeta err", logx.Field("detail", err.Error()))
						if err != model.ErrNotFound {
							tx.Rollback()
							return nil, err
						}
					}

					modified = true
				}
			}
		}
	}

	if modified {
		tx.Commit()
	}

	return &user.BaseResp{
		Msg: i18n.UpdateSuccess,
	}, nil
}
